import {Injectable} from '@nestjs/common';
import {InjectRepository} from "@nestjs/typeorm";
import {EntityManager, In, Repository} from "typeorm";
import {OrderEntity} from "./order.entity";
import {ResultVo} from "../../vo/common/result.vo";
import {QueryOrderVo} from 'src/vo/order/query-order.vo';
import {OrderStatusEnum} from 'src/enum/order-status.enum';
import {PageResVo} from 'src/vo/common/page.res.vo';
import {OrderItemEntity} from './order-item.entity';
import {OrderListResVo} from 'src/vo/order/order-list-res.vo';
import {OrderItemResVo} from 'src/vo/order/order-item-res.vo';
import {CreateOrderVo} from 'src/vo/order/create-order.vo';
import {CartEntity} from '../cart/cart.entity';
import {ApiCodeEnum} from 'src/enum/api-code.enum';
import {generateCode} from 'src/utils/common.utils';
import {ProductEntity} from '../product/product.entity';
import {CancelOrderVo} from 'src/vo/order/cancel-order.vo';
import {DeliveryAddressEntity} from '../deliveryAddress/delivery-address.entity';
import {IntegralPayVo} from "../../vo/order/integral-pay.vo";
import {MemberEntity} from "../member/member.entity";
import {Md5} from "ts-md5";
import {PayWaterEntity} from "../payWater/pay-water.entity";
import {PayWayEnum} from "../../enum/pay-way.enum";
import {OrderDetailVo} from "../../vo/order/order-detail.vo";

@Injectable()
export class OrderService {
    constructor(
        @InjectRepository(OrderEntity)
        private readonly orderRepository: Repository<OrderEntity>,

        @InjectRepository(OrderItemEntity)
        private readonly orderItemRepository: Repository<OrderItemEntity>,

        @InjectRepository(CartEntity)
        private readonly cartRepository: Repository<CartEntity>,

        @InjectRepository(ProductEntity)
        private readonly productRepository: Repository<ProductEntity>,

        @InjectRepository(DeliveryAddressEntity)
        private readonly deliveryAddressRepository: Repository<DeliveryAddressEntity>,

        @InjectRepository(MemberEntity)
        private readonly memberEntityRepository: Repository<MemberEntity>,

        @InjectRepository(PayWaterEntity)
        private readonly payWaterEntityRepository: Repository<PayWaterEntity>,
    ) { }

    async cancelOrder(cancelOrderVo: CancelOrderVo, manager: EntityManager) {
        console.log("取消订单:", cancelOrderVo);
        // 查询原订单信息
        let order: OrderEntity = await manager.findOne(OrderEntity, { orderCode: cancelOrderVo.orderCode, userId: cancelOrderVo.userId })
        if (!order) return ResultVo.exception(ApiCodeEnum.ORDER_NOT_EXIST)
        // 查询子订单信息
        let orderItems: OrderItemEntity[] = await manager.find(OrderItemEntity, { orderCode: cancelOrderVo.orderCode, userId: cancelOrderVo.userId })
        if (!orderItems) return ResultVo.exception(ApiCodeEnum.ORDER_NOT_EXIST)
        // 修改订单状态
        order.status = OrderStatusEnum.CANCEL
        let orderRes = await manager.update(OrderEntity, { id: order.id }, order)
        console.log("更新订单状态:", orderRes);
        // 归还库存
        for (let index = 0; index < orderItems.length; index++) {
            const item = orderItems[index];
            let product = await manager.findOne(ProductEntity, { id: item.productId })
            let stock = product.stock + item.num
            let version = product.version
            let updateRes = await manager.update(ProductEntity, { id: product.id, version }, { stock, version: version + 1 })
            console.log("归还库存:", updateRes);
            if (updateRes.affected === 0) {
                throw new Error("库存归还失败,请重新取消")
            }
        }
        return ResultVo.success()
    }

    async createOrder(createOrderVo: CreateOrderVo, manager: EntityManager) {
        // 查询购物车信息
        console.log("查询购物车信息", createOrderVo);
        const carts = await this.cartRepository.find({ id: In(createOrderVo.cartIdList), userId: createOrderVo.userId })
        if (!carts) return ResultVo.exception(ApiCodeEnum.SYS_ERROR);

        // 查询收货地址信息
        const delivertAddress = await this.deliveryAddressRepository.findOne({ id: createOrderVo.deliveryAddressId })
        if (!delivertAddress) return ResultVo.exception(ApiCodeEnum.DELIVERY_ADDRESS_NOT_EXIST);

        // 查询商品信息并验价
        console.log("验证价格验证库存");
        const productIds = carts.map(cart => cart.productId)
        let products = await this.productRepository.find({ id: In(productIds) })
        if (!products) return ResultVo.exception(ApiCodeEnum.SYS_ERROR)
        let productMap = new Map<number, ProductEntity>();
        products.forEach(product => {
            productMap[product.id] = product
        })
        let errorMsg: string = ""
        console.log("商品数据:", productMap);

        carts.forEach(cart => {
            if (!productMap[cart.productId]) {
                errorMsg += "商品:" + cart.productName + "已下架;"
            } else {
                const product: ProductEntity = productMap[cart.productId]
                console.log(product.salePrice, cart.price);
                if (new Number(cart.price).toFixed(4) != new Number(product.salePrice).toFixed(4)) {
                    errorMsg += "商品:" + product.productName + "价格已变更;"
                }
                console.log(product.stock, cart.num);

                if (product.stock < cart.num) {
                    errorMsg += "商品:" + product.productName + "库存不足;"
                }
            }
        })
        if (errorMsg) return ResultVo.fail(errorMsg)
        //扣库存
        console.log("扣减库存");
        for (let index = 0; index < carts.length; index++) {
            const cart = carts[index];
            const product = productMap[cart.productId]
            const stock = product.stock - cart.num
            let version = product.version
            let updateRes = await manager.update(ProductEntity, { id: product.id, version: version }, { stock: stock, version: version + 1 })
            console.log("更新库存:===>", updateRes);
            if (updateRes.affected == 0) {
                console.log("更新库存失败!");
                throw new Error("下单失败,请稍后重试!")
            }
        }
        console.log("库存扣减完成,开始生成订单...");

        // 根据购物车数据计算订单信息
        console.log("生成订单");
        let order = new OrderEntity()
        // 生成订单号
        const orderCode = generateCode("ZDT")
        let totalNum: number = 0
        let totalPrice: number = 0
        for (let index = 0; index < carts.length; index++) {
            const cart = carts[index];
            let item = new OrderItemEntity()
            item.orderCode = orderCode
            item.productId = cart.productId
            item.productName = cart.productName
            item.productImg = cart.productImg
            item.num = cart.num
            item.price = cart.price
            item.userId = createOrderVo.userId
            totalNum += item.num
            totalPrice += item.num * item.price
            await manager.save(OrderItemEntity, item)
        }

        // 设置订单信息
        order.orderCode = orderCode
        order.num = totalNum
        order.totalPrice = totalPrice
        order.userId = createOrderVo.userId
        order.status = OrderStatusEnum.FOR_PAY
        order.deliveryAddress = JSON.stringify(delivertAddress)
        await manager.save(OrderEntity, order)

        // 删除购物车数据
        for (let index = 0; index < carts.length; index++) {
            const cart = carts[index];
            let delRes = await manager.delete(CartEntity, cart.id)
            console.log("删除购物车:", delRes);
            if (delRes.affected == 0) {
                throw new Error("下单异常,异常原因:删除购物车失败!")
            }
        }
        return ResultVo.successWithData({ orderCode })
    }

    async queryOrdersByPage(queryOrderVo: QueryOrderVo) {
        console.log("queryOrdersByPage:", queryOrderVo)
        let qb = this.orderRepository.createQueryBuilder()
        // 拼接条件
        let query = new OrderEntity()
        if (queryOrderVo.status >= 0) {
            query.status = queryOrderVo.status
        }
        query.userId = queryOrderVo.userId
        qb.where(query as Partial<OrderEntity>)
        // 排序
        qb.addOrderBy("updated_time", "DESC")
        // 分页
        qb.skip(queryOrderVo.size * (queryOrderVo.page - 1)).take(queryOrderVo.size)
        // 查询数据
        let [resData, total] = await qb.getManyAndCount()
        // 实体转化
        let voList: OrderListResVo[] = JSON.parse(JSON.stringify(resData))
        // 查询item子订单
        if (voList && voList.length > 0) {
            let orderCodes: string[] = voList.map(order => order.orderCode)
            let orderItems: OrderItemEntity[] = await this.orderItemRepository.find({ orderCode: In(orderCodes) })
            if (orderItems && orderItems.length > 0) {
                let map = new Map<string, OrderItemResVo>();
                orderItems.forEach(row => {
                    if (map[row.orderCode]) {
                        map[row.orderCode].push(JSON.parse(JSON.stringify(row)));
                    } else {
                        let list = [];
                        list.push(JSON.parse(JSON.stringify(row)));
                        map[row.orderCode] = list;
                    }
                    // map[row.orderCode] = JSON.parse(JSON.stringify(row))
                })
                voList.forEach(order => {
                    if (map[order.orderCode]) {
                        order.orderItems = map[order.orderCode]
                    }
                })
            }
        }
        // 构建分页返回公共参数
        let pageResVo = PageResVo.generatePage(queryOrderVo, total, voList);
        return ResultVo.successWithData(pageResVo)
    }

    async queryAll() {
        let data = await this.orderRepository.find()
        return ResultVo.successWithData(data)
    }

    async queryOne(id: number | string) {
        let data = await this.orderRepository.findOne(id)
        return ResultVo.successWithData(data)
    }

    async queryByOrderCode(userId: number, orderCode:  string) {
        let data = await this.orderRepository.find({where:{userId,orderCode}})
        if(data){
            let orderInfo = data[0]
            let resVo: OrderListResVo = JSON.parse(JSON.stringify(orderInfo))
            let orderItems: OrderItemEntity[] = await this.orderItemRepository.find({ orderCode: orderInfo.orderCode })
            resVo.orderItems = orderItems
            return ResultVo.successWithData(resVo)
        }
        return ResultVo.fail("暂无该订单信息")
    }

    async add(data: OrderEntity) {
        let date = new Date()
        data.createdTime = date
        data.updatedTime = date
        let res = await this.orderRepository.save<OrderEntity>(data)
        return ResultVo.successWithData(res)
    }

    async edit(data: OrderEntity) {
        data.updatedTime = new Date()
        let res = await this.orderRepository.update({ id: data.id }, data)
        return ResultVo.successWithData(res)
    }

    async delete(id: number | string) {
        let res = await this.orderRepository.delete(id)
        return ResultVo.successWithData(res)
    }

    /**
     * 积分支付
     * @param integralPayVo
     * @param manager
     */
    async integralPay(integralPayVo: IntegralPayVo, manager: EntityManager) {
        console.log("积分支付:",integralPayVo)
        // 查询用户信息
        let userInfo = await this.memberEntityRepository.findOne({id:integralPayVo.userId})
        if(!userInfo){
            return ResultVo.exception(ApiCodeEnum.USER_NOT_EXIST)
        }
        // 支付密码判断
        if(!userInfo.payPassword){
            return ResultVo.exception(ApiCodeEnum.PAY_PASS_NOT_EXIST)
        }
        let payPassword = Md5.hashStr(integralPayVo.payPassword)
        if(payPassword != userInfo.payPassword){
            return  ResultVo.exception(ApiCodeEnum.PAY_PASS_ERROR)
        }
        // 支付积分判断
        let totalIntegral = userInfo.integral
        if(totalIntegral < integralPayVo.payIntegral){
            return ResultVo.exception(ApiCodeEnum.INTEGRAL_NOT_ENOUGH)
        }

        // 查询订单信息
        let orderInfo = await this.orderRepository.findOne({orderCode: integralPayVo.orderCode})
        if(!orderInfo){
            return ResultVo.exception(ApiCodeEnum.ORDER_NOT_EXIST)
        }
        if(orderInfo.totalPrice != integralPayVo.payIntegral){
            return ResultVo.exception(ApiCodeEnum.INTEGRAL_NOT_MATCH_ORDER)
        }

        // 更新订单
        orderInfo.payTime = new Date()
        orderInfo.tradeCode = generateCode("JF")
        orderInfo.status = OrderStatusEnum.FOR_DILIVER
        orderInfo.realPay = integralPayVo.payIntegral
        let orderRes = await manager.update(OrderEntity,{id:orderInfo.id},orderInfo)
        console.log("更新订单：",orderRes)

        // 添加支付流水日志
        let payWater = new PayWaterEntity()
        payWater.orderCode = integralPayVo.orderCode
        payWater.payWay = PayWayEnum.INTEGRAL
        payWater.payAmount = integralPayVo.payIntegral
        payWater.payBeforeAmount = userInfo.integral
        payWater.payAfterAmount = userInfo.integral - integralPayVo.payIntegral
        payWater.userId = integralPayVo.userId
        payWater.tradeCode = orderInfo.tradeCode
        let payWaterRes = await manager.save(PayWaterEntity,payWater)
        console.log("支付流水保存：", payWater, payWaterRes)

        // 扣减积分
        let userRes = await manager.update(MemberEntity,{id: userInfo.id,integral: userInfo.integral},{integral:userInfo.integral - integralPayVo.payIntegral})
        if(userRes.affected != 1){
            throw new Error("支付失败，请稍后重试！")
        }

        return ResultVo.successWithData(orderInfo)

    }

    /**
     * 再次购买
     * @param orderDetailVo
     * @param manager
     */
    async againBuy(orderDetailVo: OrderDetailVo, manager: EntityManager) {
        let resData = []
        // 查询订单数据
        let orderItems = await this.orderItemRepository.find({orderCode:orderDetailVo.orderCode, userId:orderDetailVo.userId})
        if(!orderItems){
            return ResultVo.exception(ApiCodeEnum.ORDER_NOT_EXIST)
        }
        for (let i = 0; i < orderItems.length; i++) {
            let item = orderItems[i]
            let product = await this.productRepository.findOne({ id: item.productId })
            if (!product) {
                return ResultVo.exception(ApiCodeEnum.PRODUCT_NOT_EXIST)
            }
            let date = new Date()
            let data = { productId: item.productId, productName: product.productName, productImg: product.headImg, num: item.num, price: product.salePrice, userId: item.userId, createdTime: date, updatedTime: date, id: null }
            let cart = await this.cartRepository.findOne({ userId: item.userId, productId: item.productId })
            // 新增购物车商品
            if (cart) {
                console.log("购物车里已经存在该商品,直接更新库存");
                cart.num = item.num
                cart.price = product.salePrice
                cart.productName = product.productName
                cart.productImg = product.headImg
                await manager.update(CartEntity,{ id: cart.id }, cart)
                resData.push(cart)
            } else {
                await manager.save(CartEntity,data)
                resData.push(data)
            }
        }
        return ResultVo.successWithData(resData)
    }
}
